#pragma once
#ifndef _APPLICATION_H_
#define _APPLICATION_H_
#ifdef WIN32
#pragma execution_character_set("utf-8")
#endif

#include <QObject>
#include <QQueue>
#include <QMutex>
#include<QTimer>
#include "projectConfig.h"
#include "configuration.h"
#include "utils.h"
#include "camera.h"
#include "SerialPort.h"
#include "threads.h"
#include "MyError.h"
#include "MyModel.h"
#include"dao.h"

/// <summary>
/// 程序主控对象
/// </summary>
class AppService : public QObject {
	
	Q_OBJECT
private:
	const QString STRETCHED = QString("11");  //拉伸薄膜

	const QString LOOSE=QString("12"); //松散薄膜

	const QString STOP = QString("13");//停止

signals:
	// 上传点云数据到主窗口
	void sendCloud2mainwindow(pcl::PointCloud<pcl::PointXYZ>::Ptr& data,staticalParameters cloudStaticData);

	/// <summary>
	/// 接收到图像的信号
	/// </summary>
	void frameReceive(cv::Mat& frame);

	/// <summary>
	/// 检测完成的信号
	/// </summary>
	/// <param name="data">检测的数据</param>
	void testFinished(const cv::Mat& data, const MyError& error);

	/// <summary>
	/// 上传错误信息
	/// </summary>
	/// <param name="e"></param>
	void scannerError(const MyError& e);

public:

	AppService();

	~AppService();

	/// <summary>
	/// 连接相机
	/// </summary>
	void connectCamera();

	/// <summary>
	/// 设置相机参数
	/// </summary>
	/// <param name="config"></param>
	void setCameraParams(const CameraConfig& config);

	/// <summary>
	/// 打开相机预览
	/// </summary>
	void startCameraLive();

	/// <summary>
	/// 关闭相机预览
	/// </summary>
	void stopCameraLive();

	/// <summary>
	/// 关闭相机
	/// </summary>
	void closeCamera();

	/// <summary>
	/// 连接串口
	/// </summary>
	void connectSerialPort();

	/// <summary>
	/// 连接伺服驱动串口
	/// </summary>
	void connectServoPort();


	/// <summary>
	/// 关闭串口
	/// </summary>
	void closeSerialPort();

	/// <summary>
	/// 更新485串口的参数
	/// </summary>
	/// <param name="config"></param>
	void update485Params(const SerialPortConfig& config);

	/// <summary>
	/// 移动平台到末尾
	/// </summary>
	void movePlatformToTail();

	/// <summary>
	/// 重置平台位置
	/// </summary>
	void resetPlatform(bool waitReset = true);

	/// <summary>
	/// 停止平台移动
	/// </summary>
	void stopPlatformMove();

	/// <summary>
	/// 控制激光器的开关
	/// </summary>
	/// <param name="enableLight"></param>
	void laserControl(QString enableLight);

	/// <summary>
	/// 控制伺服
	/// </summary>
	/// <param name="controlData">控制数据</param>
	/// <returns></returns>
	bool servoControl(QString controlData);

	/// <summary>
	/// 主动轮控制
	/// </summary>
	/// <param name="controlData"></param>
	/// <returns></returns>
	bool activeWheelControl(QString controlData);

	/// <summary>
	/// 被动轮控制
	/// </summary>
	/// <param name="controlData"></param>
	/// <returns></returns>
	bool passiveWheelControl(QString controlData);


	/// <summary>
	/// 连接数据库
	/// </summary>
	void connectDatabase();

	/// <summary>
	/// 显示检测数据
	/// </summary>
	/// <param name="table"></param>
	/// <param name="dataList"></param>
	/// <param name="minRows"></param>
	void showTestData(QTableWidget* table, QList<DaoModel::TestData>& dataList, int minRows);


	/// <summary>
	///	清空数据库连接
	/// </summary>
	void clearDatabaseConnections();

	/// <summary>
	/// 获取APP版本
	/// </summary>
	QString getAppVersion();

	/// <summary>
	/// 返回程序构建类型
	/// </summary>
	/// <returns></returns>
	QString getBuildType();

	/// <summary>
	/// 获取配置文件
	/// </summary>
	/// <returns></returns>
	Configuration& getConfig();

	/// <summary>
	/// 保存配置文件
	/// </summary>
	void saveConfig();

	/// <summary>
	/// 保存检测记录
	/// </summary>
	/// <param name="record"></param>
	void saveTestRecord(MyModel::TestRecord& record);

	/// <summary>
	/// 保存检测数据
	/// </summary>
	/// <param name="data"></param>
	void saveTestData(MyModel::TestData& data);

	/// <summary>
	/// 开始检测
	/// </summary>
	/// <param name="record"></param>
	void startTest();

	/// <summary>
	/// 涨紧薄膜
	/// </summary>
	void stretchedFilm();

	/// <summary>
	/// 松散薄膜
	/// </summary>
	void losseFilm();

	//延时操作
	void delay(int milliseconds, std::function<void()> callback, QObject* context = nullptr);

	//删除指定序号的数据库数据
	void deleteRecords(qint64 m_id);

	//保存数据
	void saveData(DaoModel::TestData& data);

	//判断数据库有没有打开
	bool isDBOpen(); 

	//查询数据库记录
	void querySqlTestRecords(QList<DaoModel::TestData>& records, QDate& beginDay, QDate& endDay, QString tester, QString schedule);

	//删除数据库数据
	void deleteSqlRecord(qint64 id);

	//批量删除数据
	void deleteSqlRecords(vector<qint64> ids);

	//查询数据
	void querySqlTestData(QList<DaoModel::TestData>& dataList, QString createTime);

	//添加检测参数
	void addSqlTestParam(const QString& tableName, const QString& name);

	//查询检测参数
	void querySqlTestParam(const QString& tableName, QStringList& names);

	//查询历史参数
	void querySqlHistoryTestParams(QStringList& tester, QStringList& schedules);

private slots:

	void onFrameReceive(int num, cv::Mat& frame);

	/// <summary>
	/// 当扫描并且图像处理完成后触发的槽函数
	/// </summary>
	//void onScannerImageProcessFinished(cv::Mat& data);
	// void onScannerImageProcessFinished(vector<cv::Vec3f>& data);
	// 得到点云数据
	void onScannerImageProcessFinished(pcl::PointCloud<pcl::PointXYZ>::Ptr&,staticalParameters cloudStaticData);

	/// <summary>
	/// 图像处理线程完成后的处理函数
	/// </summary>
	void onDataAnalysisTaskFinished();

private:

	//配置文件
	Configuration& m_config;

	//数据库控制对象
	Dao m_dao;

	//相机控制对象	
	Camera m_camera;

	//保护frameQueue
	QMutex m_mutex;

	// 图像处理线程
	ImageProcessWorker* m_imageProcessWorker = nullptr;

	// 线程池
	QThreadPool m_threadPool;

	//运动控制的串口
	RS485Port m_485;

	//伺服和激光器控制
    SerialPort m_serialPort;

	//读取扭力值的串口
	//RS232Port m_232;
	int number1 = 0;

};

#endif



